import java.util.Arrays;
import java.util.Scanner;

class SLF {
    /**
     * @Class 内部类PCB 模拟进程控制块
     * @Description shortFirst
     */
    private static class PCB implements Comparable<PCB> {
        String id;
        float reachTime; //到达时间
        float needTime;  //需要时间
        float startTime; //开始时间
        float finishTime;//结束时间
        char state;
        //重写比较器
        public int compareTo( PCB b ) {
            if( reachTime == b.reachTime )
                return Float.compare(needTime ,b.needTime);
            if( reachTime < b.reachTime )
                return -1;
            return 1;
        }
    }
    private static int findNext( PCB[] arr, float lastTime ) {
        int i, p = -1;
        float minNeedTime = Float.MAX_VALUE;
        for( i = 0; i < arr.length; i++ ) {
            if( arr[i].state == 'R' ) {
             /* 数组arr已经按reachTime排序,当出现
                arr[i].reachTime>lastTime时,说明在lastTime时刻无进程到达,终止循环。*/
                if( arr[i].reachTime > lastTime )
                    break;
                if( arr[i].needTime < minNeedTime ){
                    p = i;
                    minNeedTime = arr[i].needTime;
                }
            }
        }
        if( p != -1 )
            return p;
        return i;
    }

    /**
     * function: main方法
     */
    public static void main( String[] args ) {
        Scanner sc = new Scanner( System.in );
        /*获取到进程数组*/
        System.out.print( "请输入进程数:" );
        int num = sc.nextInt();
        PCB[] arr = new PCB[num];
        System.out.println( "请依次输入进程ID,进程到达时间,进程运行时间:" );
        for( int i = 0; i < num; i++ ) {
            arr[i] = new PCB();
            arr[i].id = sc.next();
            arr[i].reachTime = sc.nextFloat();
            arr[i].needTime = sc.nextFloat();
            arr[i].state = 'R';
        }
        // 使进程按reachTime(到达时间)排序。
        Arrays.sort(arr);
        /*
         * 输出具体运行过程：
         *  此时设每个进程处于
         *   1.就绪R(Ready);
         *   2.运行E(Excecuting);
         *   3.完成F(Finish).
         *  三种状态之一,并假设起始状态都是就绪状态。
         */
        int p = 0;
        int cnt = 0;
        for(float time = arr[p].reachTime; cnt < num; time+=0.5 ){
            if( arr[p].reachTime <= time && arr[p].state == 'R' ){
                // 记录开始时间
                arr[p].startTime = time;
                arr[p].state = 'E';
                System.out.format( "在%.2f时刻: ", time );
                System.out.format( "进程%s开始运行\n", arr[p].id );
            }else if( time-arr[p].startTime < arr[p].needTime && arr[p].state == 'E'){
                System.out.format( "在%.2f时刻: ", time );
                System.out.format( "进程%s正在运行\n", arr[p].id );
            }else if( time-arr[p].startTime >= arr[p].needTime && arr[p].state == 'E'){
                arr[p].finishTime = time;  // 记录完成时间
                arr[p].state = 'F';
                System.out.format( "在%.2f时刻: ", time );
                System.out.format( "进程%s完成运行\n\n", arr[p].id );

                //找到下一个要执行的进程。
                p = findNext( arr, time );
                //用于判断结束时刻是否将有进程运行。
                time -= 0.5;
                //已经完成cnt个进程。
                cnt++;
            }
        }

    }
}
